<template>
  <el-row :gutter="10" justify="space-between" class="mb-10px">
    <slot />

    <el-col :span="6" class="top-right-btn">
      <el-tooltip :content="showSearch ? '隐藏筛选项' : '显示筛选项'" placement="top">
        <el-button circle :icon="Search" @click="toggleSearch" />
      </el-tooltip>

      <el-tooltip content="刷新列表" placement="top">
        <el-button circle :icon="Refresh" @click="refresh" />
      </el-tooltip>

      <el-tooltip content="配置列表展示字段" placement="top" v-if="columns?.length">
        <span style="display: inline-block">
          <el-popover :visible="setShow" placement="left-start" width="300">
            <div class="checkbox-main">
              <div class="flex justify-between">
                <el-checkbox
                  v-model="checkAll"
                  :indeterminate="isIndeterminate"
                  @change="onCheckAll"
                  class="checkAll-btn"
                >
                  全选
                </el-checkbox>
                <el-tooltip content="点击可重置字段配置" placement="top">
                  <el-button size="small" circle type="info" :icon="Delete" @click="onReset" />
                </el-tooltip>
              </div>

              <el-checkbox-group v-model="setValue" @change="onChecked">
                <VueDraggable
                  v-model="initialColumns"
                  animation="300"
                  handle=".drag"
                  v-if="initialColumns.length"
                >
                  <template #item="{ element, index }">
                    <div
                      class="checkbox-div"
                      v-if="!['selection', 'index', 'operation'].includes(element.prop)"
                    >
                      <el-checkbox :label="element.prop" :key="index">
                        {{ element.label }}
                      </el-checkbox>
                      <div>
                        <el-button class="count" size="small" link> | {{ index }} | </el-button>
                        <el-button class="drag" size="small" text bg type="primary">
                          拖动
                        </el-button>
                      </div>
                    </div>
                  </template>
                </VueDraggable>
              </el-checkbox-group>
            </div>
            <footer class="text-right m-0px pt-10px">
              <el-button size="small" type="text" @click="handleFieldVisible"> 取消 </el-button>
              <el-button size="small" type="primary" @click="handleFieldSubmit" :loading="loading">
                确定
              </el-button>
            </footer>

            <template #reference>
              <el-button circle :icon="Operation" @click="handleFieldVisible" class="ml-12px" />
            </template>
          </el-popover>
        </span>
      </el-tooltip>
    </el-col>
  </el-row>
</template>

<script lang="ts" setup>
import { cloneDeep, differenceWith, isEqual, pullAll, concat } from 'lodash-es'
import { useUserStore } from '@/store/modules/user'
import { Search, Refresh, Operation, Delete } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import VueDraggable from 'vuedraggable'

interface Column {
  prop: string
  label: string
}

const props = defineProps({
  showSearch: {
    type: Boolean,
    default: true
  },
  columns: {
    type: Array as () => Array<any>,
    default: () => []
  }
})
const emit = defineEmits(['update:showSearch', 'refreshTable', 'update:columns'])

const userStore = useUserStore()
const loading = ref(false)
const originColumns = ref<Column[]>([]) // 初始数据 重置的时候用
const initialColumns = ref<Column[]>([]) // 配置的时候用的数据
const originalInitialColumns = ref<Column[]>([]) // 每次点开弹窗的时候  保留当前配置的数据
const setShow = ref(false)
const setValue = ref<string[]>([])
const originalSetValue = ref<string[]>([])
const checkAll = ref(false)
const columnsKeys = computed(() => initialColumns.value.map((p) => p?.prop) ?? [])

const isIndeterminate = computed(() => {
  return setValue.value.length > 0 && setValue.value.length < initialColumns.value.length
})

const toggleSearch = () => {
  emit('update:showSearch', !props.showSearch)
}

const refresh = () => {
  emit('refreshTable')
}

const onCheckAll = (checked: boolean) => {
  setValue.value = checked ? columnsKeys.value : []
}

const defaultArr = ['selection', 'index', 'operation']
const onChecked = (checkedList: string[]) => {
  // 使用differenceWith()方法获取checkedList中存在而defaultArr中不存在的元素
  const diff = differenceWith(checkedList, defaultArr)
  // 检查是否有差集，length>0 代表有差值，也就是有选项
  const isSubset = diff.length === 0
  if (isSubset) {
    setValue.value = []
    checkAll.value = false
  } else {
    checkAll.value = checkedList.length === initialColumns.value.length
  }
}

const onReset = () => {
  initialColumns.value = [...originColumns.value]
  checkAll.value = true
  onCheckAll(true)
}

// 取消按钮/开启弹窗
const handleFieldVisible = () => {
  if (!!setShow.value) {
    // 取消 - 恢复数据
    setValue.value = [...originalSetValue.value]
    initialColumns.value = [...originalInitialColumns.value]
  } else {
    // 开启弹窗 - 开启时先把数据存储一遍
    originalSetValue.value = [...setValue.value]
    originalInitialColumns.value = [...initialColumns.value]
  }
  setShow.value = !setShow.value
}

// 提交
const handleFieldSubmit = () => {
  if (
    setValue.value.length === 0 ||
    (setValue.value.length <= 1 && defaultArr.some((value) => setValue.value.includes(value)))
  ) {
    return ElMessage.warning('最少选择一列显示！')
  }

  loading.value = true

  if (columnsKeys.value.includes('index') && !setValue.value.includes('index')) {
    setValue.value.unshift('index')
  }

  if (columnsKeys.value.includes('selection') && !setValue.value.includes('selection')) {
    setValue.value.unshift('selection')
  }

  if (columnsKeys.value.includes('operation') && !setValue.value.includes('operation')) {
    setValue.value.push('operation')
  }

  const sortList: string[] = []
  columnsKeys.value.forEach((item) => {
    setValue.value.forEach((p) => {
      if (item === p) sortList.push(p)
    })
  })

  const list: Column[] = []
  sortList.forEach((item) => {
    const obj = initialColumns.value.find((p) => p?.prop === item) ?? null
    if (obj) list.push(obj)
  })

  const path = window.location.pathname
  const name = computed(() => userStore.user.nickname ?? 'Admin')

  setTimeout(() => {
    emit('update:columns', list)
    setShow.value = false
    loading.value = false
    const data = {
      setValue: setValue.value,
      initialColumns: initialColumns.value
    }
    localStorage.setItem(`${name.value}-${path}`, JSON.stringify(data))
  }, 0)
}

onMounted(() => {
  if (!props.columns?.length) return false
  // 第一次加载，用initialColumns属性 拷贝一下初始table-columns
  console.log(props.columns)
  initialColumns.value = cloneDeep(props.columns)
  originColumns.value = cloneDeep(props.columns)
  // 先初始化 setValue
  setValue.value = initialColumns.value.map((item) => item.prop)
  // 取路由地址和 登录账户的名称 拼接存储
  const path = window.location.pathname
  const name = computed(() => userStore.user.nickname ?? 'Admin')
  // 然后从 localStorage里面去获取，当前用户 在当前菜单下 已调整好的列数据和已选的id
  const keys = localStorage.getItem(`${name.value}-${path}`)
  if (keys) {
    const data = JSON.parse(keys)
    // console.log('data：', data)
    console.log('初始：', originColumns.value)
    setValue.value = data.setValue
    initialColumns.value = data.initialColumns

    // diffList2 已配置好的数据中  废除的数据
    const diffList2 = differenceWith(initialColumns.value, originColumns.value, isEqual)
    const diffKey2 = diffList2.map((p) => p?.prop)
    // 将废弃的数据 从initialColumns中删除
    pullAll(initialColumns.value, diffList2)
    // 将废弃数据的ID从setValue中删除
    pullAll(setValue.value, diffKey2)

    // diffList1 更新的数据
    const diffList1 = differenceWith(originColumns.value, initialColumns.value, isEqual)
    const diffKey1 = diffList1.map((p) => p?.prop)
    // 将更新的数据 添加到initialColumns中
    initialColumns.value = concat(initialColumns.value, diffList1)
    // 将更新数据的ID 添加到setValue
    setValue.value = concat(setValue.value, diffKey1)
    // console.log('diff1：', diffList1)
    // console.log('diff2：', diffList2)
    console.log(333, initialColumns.value)
  }
  // 处理一下全选
  checkAll.value =
    setValue.value.length === initialColumns.value.length ||
    setValue.value.length === originColumns.value.length
  // console.log(checkAll.value)
  // console.log(setValue.value)
  // console.log(initialColumns.value)
  // console.log(originColumns.value)

  handleFieldSubmit()
})

onDeactivated(() => {
  // console.log('onDeactivated：', window.location.href)
  // 如果当前开启  就在离开页面的时候关闭掉
  if (!!setShow.value) handleFieldVisible()
})
</script>

<style lang="scss" scoped>
.top-right-btn {
  position: relative;
  text-align: right;
}

.checkAll-btn {
  font-size: 13px;
  font-weight: 600;
  font-family: '黑体';
  letter-spacing: 1px;
  margin-bottom: 6px;
}
.el-checkbox-group {
  display: flex;
  flex-direction: column;

  .el-checkbox {
    margin-bottom: 3px;
    overflow: hidden;
    white-space: nowrap;
    // text-overflow: ellipsis;
  }
}

.checkbox-div {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background-color: var(--el-button-hover-bg-color);
  border-radius: 6px;
  padding: 0 -10px;

  &:hover {
    background-color: var(--el-fill-color-light);
    padding: 0px 10px;
    margin: 0 -10px;
  }

  .count {
    width: 50px !important;
    margin-right: -10px;
    cursor: default;
  }
}
</style>
